package com.wanli.security;
import cn.hutool.core.util.StrUtil;
import com.wanli.domain.entity.User;
import com.wanli.service.UserService;
import com.wanli.util.JwtUtil;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.JwtException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.authentication.www.BasicAuthenticationFilter;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

@Slf4j
public class JWTAuthenticationFilter extends BasicAuthenticationFilter {
    @Autowired
    JwtUtil jwtUtil;
    @Autowired
    UserService userService;
    @Autowired
    UserDetailsServiceImpl userDetailsService;

    public JWTAuthenticationFilter(AuthenticationManager authenticationManager) {
        super(authenticationManager);
    }

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException {
        //验证token代码:
        //从前端请求的请求头中获得token
        String jwt = request.getHeader("token");
        log.info("JWT校验过滤器执行，token={}",jwt);

        //判断jwt是不是空
        if(StrUtil.isBlankOrUndefined(jwt)){
            //如果是"/api/captcha", "/login", "/logout" ，token是空，放行。
            chain.doFilter(request,response);
            return;
        }
        //因为生成 token，设置负载信息 里包含登录成功的用户名 ,解析token成功，claims对象中就存在token负载信息username
        Claims claims = jwtUtil.getClaimsByToken(jwt);
        if(claims==null){
            throw new JwtException("token解析异常");
        }
        if(jwtUtil.isTokenExpired(claims)){
            throw new JwtException("token已经过期");
        }

        //验证成功: 获得用户信息：
        String username = claims.getSubject();
        log.info("JWR验证成功，用户{}---正在访问后台系统",username);

        //Jwt验证成功，需要加载当前用户权限信息。
        User user = userService.getUserByUsername(username);
        //UsernamePasswordAuthenticationToken构造方法: 参数1用户名,null,参数3权限
        //需要获得当前登录访问用户的权限信息
        //调用登录实现类中封装的方法getUserAuthority(user.getId())
        UsernamePasswordAuthenticationToken upat = new UsernamePasswordAuthenticationToken(username,null,userDetailsService.getUserAuthority(user.getId()));
        SecurityContextHolder.getContext().setAuthentication(upat);

        chain.doFilter(request,response);
    }
}








